#pragma once 
#include "socket.hpp"
#include "eventloop.hpp"
#include "buffer.hpp"
#include "any.hpp"

enum ConnStatu
{
    DISCONNECTED, 
    CONNECTING, 
    CONNECTED, 
    DISCONNECTING 
};

class Connection;

using PtrConnection = std::shared_ptr<Connection>;

class Connection: public std::enable_shared_from_this<Connection>
{
private:
    using ConnectedCallback = std::function<void(const PtrConnection&)>;
    using MessageCallback = std::function<void(const PtrConnection&, Buffer*)>;
    using ClosedCallback = std::function<void(const PtrConnection&)>;
    using EventCallback = std::function<void(const PtrConnection&)>;

private:
    // 接受socket数据放到缓冲区，调用_message_callback
    void HandleRead()
    {
        char buf[65536]; 
        ssize_t ret = _socket.RecvNonBlock(buf, 65535);
        if(ret < 0) // 客户端连接断开等原因，需要处理剩余数据
            return ShutdownInLoop();
        _in_buffer.Write(buf, ret);

        if(_in_buffer.ReadAbleSize() > 0) // 可能由于 无数据(非阻塞) || 阻塞等待被连接打断 没有接受到数据
            _message_callback(shared_from_this(), &_in_buffer);    
    }

    // 将发送缓冲区的数据进行发送
    void HandleWrite()
    {
        uint64_t len = _out_buffer.ReadAbleSize();
        char* send_buf[len];
        _out_buffer.Read(send_buf, len, ReadOnly); // 发送数据可能会失败，因此先只读，在发送成功后再移动read_index
        ssize_t ret = _socket.SendNonBlock(send_buf, len); 
        if(ret < 0)
        {
            HandleClose();
        } 

        _out_buffer.MoveReadIndex(ret);

        if(_out_buffer.ReadAbleSize() == 0)
        {
            _channel.DisableWrite();
            if(_statu == DISCONNECTING) 
            {
                Release();
            }
        }
    }

    void HandleClose()
    {
        if(_in_buffer.ReadAbleSize() > 0)
            _message_callback(shared_from_this(), &_in_buffer);
        return Release();
    }

    void HandleError()
    {
        HandleClose();
    }

    // 刷新活跃度、调用回调函数
    void HandleEvent()
    {
        if(_enable_inactive_release)    
            _loop->TimerRefresh(_conn_id);
        if(_event_callback)
            _event_callback(shared_from_this());
    }

    // 获取连接后，修改连接状态，启动读事件监控，调用回调函数
    void EstablishedInLoop()
    {
        assert(_statu == CONNECTING);
        _statu = CONNECTED;
        _channel.EnableRead();
        if(_connected_callback)
            _connected_callback(shared_from_this());
    }

    // 释放接口，关闭socket套接字，移除channel和定时任务，调用close回调函数
    void ReleaseInLoop()
    {
        _statu = DISCONNECTED;
        _channel.Remove();
        _socket.Close();
        if(_loop->HasTimer(_conn_id))
            ChannelInactiveReleaseInLoop();
        if(_close_callback) 
            _close_callback(shared_from_this());
        if(_server_closed_callback)
            _server_closed_callback(shared_from_this());
    }

    void Release()
    {
        _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));    
    }

    void SendInLoop(Buffer& buffer)    
    {
        if(_statu == DISCONNECTED)
            return ;
        _out_buffer.Write(buffer);
        if(_channel.WriteAble() == false)
            _channel.EnableWrite();
    }

    // 处理剩余数据
    void ShutdownInLoop()
    {
        _statu = DISCONNECTING;
        if(_in_buffer.ReadAbleSize())
        {
            if(_message_callback)
                _message_callback(shared_from_this(), &_in_buffer);
        }
        if(_out_buffer.ReadAbleSize())
        {
            if(_channel.WriteAble() == false)
                _channel.EnableWrite();
        }
        if(_out_buffer.ReadAbleSize() == 0)
        {
            Release();
        }
    }

    //非活跃连接超时释放
    void EnableInactiveReleaseInLoop(int sec)
    {
        _enable_inactive_release = true;
        if(_loop->HasTimer(_conn_id))
            _loop->TimerRefresh(_conn_id);
        else
            _loop->TimerAdd(_conn_id, sec, std::bind(&Connection::Release, this));
    }

    void ChannelInactiveReleaseInLoop()
    {
        _enable_inactive_release = false;
        if(_loop->HasTimer(_conn_id))
            _loop->TimerCancel(_conn_id); 
    }

    void UpgradeInLoop(const Any& context, const ConnectedCallback& conn_cb, const MessageCallback& mess_cb, 
                    const ClosedCallback& close_cb, const EventCallback& event_cb)
    {
        _context = context;
        _connected_callback = conn_cb;
        _message_callback = mess_cb;
        _close_callback = close_cb;
        _event_callback = event_cb;
    }

public:
    Connection(uint64_t conn_id, int sockfd, EventLoop* loop)
    : _conn_id(conn_id), _sockfd(sockfd), _loop(loop), _socket(sockfd), _channel(loop, sockfd)
    {
        _channel.SetReadCallBack(std::bind(&Connection::HandleRead, this));
        _channel.SetWriteCallBack(std::bind(&Connection::HandleWrite, this));
        _channel.SetCloseCallBack(std::bind(&Connection::HandleClose, this));
        _channel.SetErrorCallBack(std::bind(&Connection::HandleError, this));
        _channel.SetEventCallBack(std::bind(&Connection::HandleEvent, this));
    }

    int GetId() { return _conn_id; }
    int GetFd() { return _sockfd; }
    bool IsConnected() { return _statu == CONNECTED; }

    void SetContext(const Any& context) { _context = context; }
    Any* GetContext()   { return &_context; }
    void SetConnectedCallback(const ConnectedCallback& conn_cb) { _connected_callback = conn_cb; }
    void SetMessageCallback(const MessageCallback& mess_cb) { _message_callback = mess_cb; }
    void SetCloseCallback(const ClosedCallback& close_cb)   { _close_callback = close_cb; }
    void SetEventCallback(const EventCallback& event_cb)    { _event_callback = event_cb; }
    void SetServerCloseCallback(const ClosedCallback& ser_close_cb) { _server_closed_callback = ser_close_cb; }

    // 获取连接后，修改连接状态，启动读事件监控， 调用回调函数
    void Established()  
    {
        _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this)); 
    }

    void Send(const char* data, uint64_t len)   
    {
        //该函数只是将发送任务压入到任务池当中，当真正执行发送任务(SendInLoop函数)时，data空间可能已经被释放
        Buffer buffer;
        buffer.Write(data, len);
        _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buffer))); 
    }

    // 处理剩余数据
    void Shutdown() 
    {
        _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this)); 
    }

    // 非活跃连接超时释放
    void EnableInactiveRelease(int sec) 
    { 
        _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec)); 
    }

    void ChannelInactiveRelease()   
    { 
        _loop->RunInLoop(std::bind(&Connection::ChannelInactiveReleaseInLoop, this)); 
    }

    // 切换协议
    void Upgrade(const Any& context, const ConnectedCallback& conn_cb, const MessageCallback& mess_cb, 
                const ClosedCallback& close_cb, const EventCallback& event_cb)
    {
        _loop->AssertInLoop(); // 必须在EventLoop线程中执行该函数（立即执行），以避免在切换协议前新事件的触发
        _loop->RunInLoop(std::bind(&Connection::Upgrade, this, context, conn_cb, mess_cb, close_cb, event_cb)); 
    }

    ~Connection() 
    {
        logMessage(NORMAL, "release connection : %p", this); 
    }

private:
    uint64_t _conn_id;
    int _sockfd;
    bool _enable_inactive_release = false;  //非活跃连接销毁
    ConnStatu _statu = CONNECTING;
    EventLoop* _loop;
    Socket _socket;
    Channel _channel;
    Buffer _in_buffer; 
    Buffer _out_buffer;
    Any _context;   //请求的接受处理上下文

    ConnectedCallback _connected_callback; 
    MessageCallback _message_callback;
    ClosedCallback _close_callback;    // 用户的关闭处理
    EventCallback _event_callback;
    ClosedCallback _server_closed_callback; // 移除服务器内部的连接管理信息
};     